package com.tfleo.mealssenger;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject;

import com.github.ignition.core.widgets.RemoteImageView;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.tfleo.mealssenger.R;
import com.tfleo.mealssenger.adapter.FriendCheckBoxAdapter;
import com.tfleo.mealssenger.balloon.CustomOverlayItem;
import com.tfleo.mealssenger.balloon.PlacesOverlay;
import com.tfleo.mealssenger.balloon.UsersOverlay;
import com.tfleo.mealssenger.object.FriendSelection;
import com.tfleo.mealssenger.object.Place;
import com.tfleo.mealssenger.object.Suggestion;
import com.tfleo.mealssenger.utility.DataFetcher;
import com.tfleo.mealssenger.utility.PlaceIconFetcher;
import com.tfleo.mealssenger.utility.StaticMapFetcher;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.app.TimePickerDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.Secure;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RatingBar;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import android.widget.RatingBar.OnRatingBarChangeListener;
import android.widget.ViewSwitcher;

public class SuggestionActivity extends MapActivity {
	private static final int TIME_DIALOG_ID = 0;
	private static final int DATE_DIALOG_ID = 1;
	private static final String TAG = "SuggestionActivity";

	private LayoutInflater mInflater;
	private ListView vGuestList;
	private EditText vMessage;
	private TextView vContext;
	private TextView vPlaceName;
	private TextView vPlaceCategory;
	private TextView vDistance;
	private TextView vSuggestAnother;
	private Button vTimePicker;
	private Button vSendButton;
	private Button vBackButton;
	private ViewSwitcher vSwitcher;
	private RemoteImageView vMapImage;
	
	private MapView vMap;
	private MapController mMapController;
	private List<Overlay> mMapOverlays;
	private PlacesOverlay mPlacesOverlay;
	private UsersOverlay mUsersOverlay;

	private int mUserId;
	private int mLocationId;
	
	private int mYear;
	private int mMonth;
	private int mDay;
	private int mHour;
	private int mMinute;
	
	private String mDate;
	private String mTime;
	private boolean isFree = false;
	
	private SharedPreferences mSharedPref;
	private String mAuth;

	private FriendCheckBoxAdapter mGuestAdapter;
	private Place curPlace;
	private int curIndex;
	private Context mContext;
	
	private Suggestion s;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.suggestion_layout);
		mContext = this;
		mInflater = (LayoutInflater) getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
		mSharedPref = getSharedPreferences(Main.USER_DATA, MODE_PRIVATE);
		mAuth = Secure.getString(this.getContentResolver(), Secure.ANDROID_ID); //for authentication
		mUserId = mSharedPref.getInt(Main.USER_ID, 0);

		if(mUserId == 0) {
			Toast.makeText(mContext, "Error: Invalid user id!", Toast.LENGTH_SHORT).show();
			finish();
		}
		
		Bundle extras = getIntent().getExtras();
		if(extras != null) {

		} else {
			
		}
		vMap = (MapView) findViewById(R.id.map_view);
		vMap.setBuiltInZoomControls(true);
		
		mMapController = vMap.getController();

        mMapOverlays = vMap.getOverlays();
        mPlacesOverlay = new PlacesOverlay(this.getResources()
        		.getDrawable(R.drawable.place_marker), vMap);
        
        mUsersOverlay = new UsersOverlay(this.getResources()
        		.getDrawable(R.drawable.friend_marker), vMap);
		
		vSwitcher = (ViewSwitcher) findViewById(R.id.switcher);
		vMessage = (EditText) findViewById(R.id.message_box);
		vGuestList = (ListView) findViewById(R.id.guest_list);
		
		//vContext = (TextView) findViewById(R.id.context);
		vPlaceName = (TextView) findViewById(R.id.place_name);
		vPlaceCategory = (TextView) findViewById(R.id.place_category);
		vDistance = (TextView) findViewById(R.id.distance);
		vPlaceCategory = (TextView) findViewById(R.id.place_category);
		
		
		//TODO handle no place situation
		vSuggestAnother = (TextView) findViewById(R.id.suggest_another_txt);
		vSuggestAnother.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if(curIndex+1 < s.p.size()) {
					curIndex++;
					curPlace = s.p.get(curIndex);
					refreshView();
				} else {
					Toast.makeText(mContext, "No more suggestion to show!", Toast.LENGTH_SHORT).show();
					curIndex = 0;
					curPlace = s.p.get(curIndex);
					refreshView();
				}
				mPlacesOverlay.clear();
				GeoPoint otherPos = new GeoPoint(
						(int) (curPlace.latitude * 1E6),
						(int) (curPlace.longitude * 1E6));
				CustomOverlayItem thisOverlay = new CustomOverlayItem(otherPos, curPlace.id,
						curPlace.name, curPlace.description, curPlace.category, false);

				mPlacesOverlay.addOverlay(thisOverlay);
				mMapOverlays.add(mPlacesOverlay);
				
				mMapController.animateTo(otherPos);
				//mMapController.setZoom(14);
				vMap.invalidate();
			}
		});
		
		vTimePicker = (Button) findViewById(R.id.time_picker);
		vTimePicker.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				showDialog(TIME_DIALOG_ID);
			}
		});


		vSendButton = (Button) findViewById(R.id.send_btn);
		vSendButton.setOnClickListener(new OnClickListener() {
			@SuppressWarnings("unchecked")
			public void onClick(View v) {
				AddInviteTask task = new AddInviteTask();
				task.execute(mGuestAdapter.getSelected());
			}
		});
		
		vMapImage = (RemoteImageView) findViewById(R.id.map_img);
		vMapImage.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				vSwitcher.showNext();
				//TODO: place overlay on map
			}
		});
		
		vBackButton = (Button) findViewById(R.id.back_btn);
		vBackButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				vSwitcher.showPrevious();
			}
		});

		/*FetchSuggestionTask task = new FetchSuggestionTask();
		task.execute(mUserId);
*/
		final Calendar c = Calendar.getInstance();
		mYear = c.get(Calendar.YEAR);
		mMonth = c.get(Calendar.MONTH) + 1;
		mDay = c.get(Calendar.DAY_OF_MONTH);
		mHour = c.get(Calendar.HOUR_OF_DAY);
		mMinute = c.get(Calendar.MINUTE);
		//TODO: suggest best time
		mDate = mYear + "-" + mMonth + "-" + mDay;
		mTime = mHour + ":" + mMinute;
		
		FetchSuggestionTask task = new FetchSuggestionTask();
		
		if(c.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || c.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
			//get free suggestion
			task.execute(0);
		} else {
			task.execute(1);
		}
		
	}
	
	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case TIME_DIALOG_ID:
			return new TimePickerDialog(this,
					mTimeSetListener, mHour, mMinute, false);
		}
		return null;
	}

	private TimePickerDialog.OnTimeSetListener mTimeSetListener =
			new TimePickerDialog.OnTimeSetListener() {
		public void onTimeSet(TimePicker view, int hour, int minute) {
			mHour = hour;
			mMinute = minute;
			vTimePicker.setText(new StringBuilder()
					.append(pad(mHour)).append(":")
					.append(pad(mMinute)));
			
			mTime = mHour + ":" + mMinute;
		}
	};
	
	private static String pad(int c) {
	    if (c >= 10)
	        return String.valueOf(c);
	    else
	        return "0" + String.valueOf(c);
	}

	private boolean addInvite(HashMap<Integer, Boolean> friendSelected, String message) {
		StringBuilder friendId = new StringBuilder();
		for (Map.Entry<Integer, Boolean> entry : friendSelected.entrySet()) {
			if(entry.getValue()) {
				friendId.append(entry.getKey()).append(",");
			}
		}
		if(friendId.length() > 0) {
			friendId.deleteCharAt(friendId.length()-1);
		}
		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(Main.SERVER_URL + "place/" + mLocationId + "/hangout");

		try {
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("host_id", Integer.toString(mUserId)));
			nameValuePairs.add(new BasicNameValuePair("guests", friendId.toString()));
			nameValuePairs.add(new BasicNameValuePair("place_id", Integer.toString(curPlace.id)));
			nameValuePairs.add(new BasicNameValuePair("place_name", curPlace.name));
			nameValuePairs.add(new BasicNameValuePair("message", message));
			nameValuePairs.add(new BasicNameValuePair("date", mDate + " " + mTime));
			nameValuePairs.add(new BasicNameValuePair("auth", mAuth));
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

			// Execute HTTP Post Request
			ResponseHandler<String> responseHandler = new BasicResponseHandler();
			String responseBody = httpclient.execute(httppost, responseHandler);
			JSONObject response = new JSONObject(responseBody);
			if(response.getInt("code") > 0) {
				return true;
			} else {
				if(response.getInt("code") == -1) {
					Log.e("aaa", "aaa");
				}
				return false;
			}
		} catch(Exception e){
			e.printStackTrace();
		}

		return false;
	}

	private class FetchSuggestionTask extends AsyncTask<Integer, Void, Suggestion> {
		private ProgressDialog mProgressDialog;

		@Override    
		protected void onPreExecute() {       
			super.onPreExecute();
			mProgressDialog = new ProgressDialog(mContext);
			mProgressDialog.setMessage("Fetching best suggestion...");
			mProgressDialog.setCancelable(false);
			mProgressDialog.setIndeterminate(true);
			mProgressDialog.show();
		}
		
		@Override
		protected Suggestion doInBackground(Integer... op) {
			float lat = mSharedPref.getFloat(Main.LAST_LATITUDE, 0);
			float lon = mSharedPref.getFloat(Main.LAST_LONGITUDE, 0);
			
			if(op[0] == 1) {
				Log.i(TAG, "Fetching weekdays suggestion");
				return DataFetcher.fetchSuggestion(mUserId, lon, lat, mAuth);
			} else {
				Log.i(TAG, "Fetching free suggestion");
				return DataFetcher.fetchFreeSuggestion(mUserId, lon, lat, mAuth);
			}
		}

		@Override
		protected void onPostExecute(Suggestion result) {
			mProgressDialog.dismiss();
			s = result;
			mGuestAdapter = new FriendCheckBoxAdapter(mContext, 
					R.layout.add_share_list_entry, R.id.name, result.g, mInflater);
			vGuestList.setAdapter(mGuestAdapter);
			
			mMapOverlays.clear();
			mPlacesOverlay.clear();
			mUsersOverlay.clear();
			
			int myLat = (int) (mSharedPref.getFloat(Main.LAST_LATITUDE, 0) * 1E6);
			int myLon = (int) (mSharedPref.getFloat(Main.LAST_LONGITUDE, 0) * 1E6);
			
			GeoPoint myPos = new GeoPoint(
					(int) (myLat),
					(int) (myLon));
			
			MapView.LayoutParams lp = new MapView.LayoutParams(
					MapView.LayoutParams.WRAP_CONTENT,
					MapView.LayoutParams.WRAP_CONTENT,
					myPos,
					MapView.LayoutParams.CENTER);
			
			ImageView myMarker = new ImageView(mContext);
			myMarker.setImageResource(R.drawable.my_marker);
			vMap.addView(myMarker, lp);
			
			int maxLat = myLat, minLat = myLat, maxLon = myLon, minLon = myLon;
			
			for(int i = 0; i < result.g.size(); i++) {
				FriendSelection u = result.g.get(i);
	
				GeoPoint otherPos = new GeoPoint(
						(int) (u.getLatitude()* 1E6),
						(int) (u.getLongitude() * 1E6));
				CustomOverlayItem thisOverlay = new CustomOverlayItem(otherPos, u.id,
						u.name, "", u.imageUrl, true);
				maxLat = Math.max(maxLat, (int)(u.getLatitude() * 1E6));
				minLat = Math.min(minLat, (int)(u.getLatitude() * 1E6));
				
				maxLon = Math.max(maxLon, (int)(u.getLongitude() * 1E6));
				minLon = Math.min(minLon, (int)(u.getLongitude() * 1E6));
				
				mUsersOverlay.addOverlay(thisOverlay);
				
			}
			mMapOverlays.add(mUsersOverlay);
			curPlace = result.p.get(0);
			
			GeoPoint otherPos = new GeoPoint(
					(int) (curPlace.latitude * 1E6),
					(int) (curPlace.longitude * 1E6));
			CustomOverlayItem thisOverlay = new CustomOverlayItem(otherPos, curPlace.id,
					curPlace.name, curPlace.description, curPlace.category, false);
			
			maxLat = Math.max(maxLat, (int)(curPlace.latitude * 1E6));
			minLat = Math.min(minLat, (int)(curPlace.latitude * 1E6));
			
			maxLon = Math.max(maxLon, (int)(curPlace.longitude * 1E6));
			minLon = Math.min(minLon, (int)(curPlace.longitude * 1E6));

			mPlacesOverlay.addOverlay(thisOverlay);
			mMapOverlays.add(mPlacesOverlay);
			
			mMapController.animateTo(new GeoPoint((maxLat + minLat)/2, 
					(maxLon + minLon)/2 ));
			double fitFactor = 1.5;
			mMapController.zoomToSpan((int) (Math.abs(maxLat - minLat) * fitFactor), 
					   (int)(Math.abs(maxLon - minLon) * fitFactor));
			vMap.invalidate();
			
			curIndex = 0;
			refreshView();
		}
	}
	
	private void refreshView() {
		vPlaceName.setText(curPlace.name);
		vDistance.setText(curPlace.getDistance() + "m from here");
		
		vMessage.setText(curPlace.getMessage());
		
        vPlaceCategory.setText(curPlace.category);
        vPlaceCategory.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(
        		PlaceIconFetcher.getIcon(curPlace.category)), null, null, null);
		
		//vMapImage.setImageUrl(StaticMapFetcher.getStaticMapUrl(Float.toString(curPlace.longitude), 
		//		Float.toString(curPlace.latitude)));
        vMapImage.setImageUrl(StaticMapFetcher.getFromLocal(curPlace.image));
		vMapImage.loadImage();
		
		
	}

	private class AddInviteTask extends AsyncTask<HashMap<Integer, Boolean>, Void, Boolean> {
		
		
		@Override
		protected Boolean doInBackground(HashMap<Integer, Boolean>... data) {
			return addInvite(data[0], vMessage.getText().toString());
		}

		@Override
		protected void onPostExecute(Boolean result) {
			if(result) {
				Toast.makeText(mContext, "Invitation sent!", Toast.LENGTH_SHORT).show();
			} else {
				Toast.makeText(mContext, "Error: Server request failed", Toast.LENGTH_SHORT).show();
			}
			finish();
		}	
	}
	
	

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}
}
